<!DOCTYPE html>
<html lang="en" class="js csstransforms3d">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta name="generator" content="Hugo 0.20.7" />
    <meta name="description" content="">


    <link rel="shortcut icon" href="http://shardingjdbc.io/document/legacy/1.x/cn/img/favicon.png" type="image/x-icon" />

    
    <title>分库分表</title>
    <link href="http://ovfotjrsi.bkt.clouddn.com/docs/css/nucleus.css" rel="stylesheet">
    <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <link href="http://ovfotjrsi.bkt.clouddn.com/docs/css/theme.css" rel="stylesheet">
    <link href="http://ovfotjrsi.bkt.clouddn.com/docs/css/hugo-theme.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
    <style type="text/css">:root #header + #content > #left > #rlblock_left
    {display:none !important;}</style>
    <link rel="stylesheet" href="http://cdn.bootcss.com/highlight.js/9.8.0/styles/monokai-sublime.min.css">
<link rel="stylesheet" href="http://ovfotjrsi.bkt.clouddn.com/docs/css/style.css">
  </head>
  <body class="" data-url="/02-guide/sharding/">
    
    <nav id="sidebar">
  <div id="header-wrapper">
    <div id="header">
      <img src="http://ovfotjrsi.bkt.clouddn.com/docs/img/sharding-jdbc.png" />
    </div>
</div>
  <div class="highlightable">
    <ul class="topics">
      
        
        
          
          
            
          
        
          
          
            
          
        
          
          
            
          
        
          
          
            
          
        
        
        
          
        
          
        
          
        
          
        
      
      
      
      

      
      
      
        
          
          
            
          
        
      
      
      

      <li class="dd-item  " data-nav-id="/00-overview/">
        <a href="http://shardingjdbc.io/document/legacy/1.x/cn/00-overview/">
          <span>
            
              <b>0. </b>
            
             概览
            
           </span>
        </a>
        
        <ul>
          
            <li class="dd-item " data-nav-id="/00-overview/intro/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/00-overview/intro/">
                <span>简介     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/00-overview/news/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/00-overview/news/">
                <span>新闻     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/00-overview/company/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/00-overview/company/">
                <span>采用公司     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/00-overview/contribution/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/00-overview/contribution/">
                <span>贡献代码     </i></span>
              </a>
            </li>
          
        </ul>
        
      </li>
      
      
      

      
      
      
        
          
          
            
          
        
      
      
      

      <li class="dd-item  " data-nav-id="/01-start/">
        <a href="http://shardingjdbc.io/document/legacy/1.x/cn/01-start/">
          <span>
            
              <b>1. </b>
            
             起航
            
           </span>
        </a>
        
        <ul>
          
            <li class="dd-item " data-nav-id="/01-start/quick-start/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/01-start/quick-start/">
                <span>快速入门     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/01-start/faq/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/01-start/faq/">
                <span>FAQ     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/01-start/features/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/01-start/features/">
                <span>详细功能列表     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/01-start/limitations/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/01-start/limitations/">
                <span>使用限制     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/01-start/sql-supported/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/01-start/sql-supported/">
                <span>SQL支持详细列表     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/01-start/stress-test/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/01-start/stress-test/">
                <span>性能测试报告     </i></span>
              </a>
            </li>
          
        </ul>
        
      </li>
      
      
      

      
      
      
        
          
          
            
          
        
      
      
      

      <li class="dd-item  parent" data-nav-id="/02-guide/">
        <a href="http://shardingjdbc.io/document/legacy/1.x/cn/02-guide/">
          <span>
            
              <b>2. </b>
            
             使用指南
            
           </span>
        </a>
        
        <ul>
          
            <li class="dd-item " data-nav-id="/02-guide/concepts/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/02-guide/concepts/">
                <span>核心概念     </i></span>
              </a>
            </li>
          
            <li class="dd-item active" data-nav-id="/02-guide/sharding/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/02-guide/sharding/">
                <span>分库分表     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/master-slave/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/02-guide/master-slave/">
                <span>读写分离     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/configuration/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/02-guide/configuration/">
                <span>配置手册     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/hint-sharding-value/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/02-guide/hint-sharding-value/">
                <span>强制路由     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/key-generator/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/02-guide/key-generator/">
                <span>分布式主键     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/transaction/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/02-guide/transaction/">
                <span>事务支持     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/subquery/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/02-guide/subquery/">
                <span>分页及子查询     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/test-framework/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/02-guide/test-framework/">
                <span>测试引擎     </i></span>
              </a>
            </li>
          
        </ul>
        
      </li>
      
      
      

      
      
      
        
          
          
            
          
        
      
      
      

      <li class="dd-item  " data-nav-id="/03-design/">
        <a href="http://shardingjdbc.io/document/legacy/1.x/cn/03-design/">
          <span>
            
              <b>3. </b>
            
             设计规划
            
           </span>
        </a>
        
        <ul>
          
            <li class="dd-item " data-nav-id="/03-design/architecture/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/03-design/architecture/">
                <span>架构设计     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/03-design/module/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/03-design/module/">
                <span>目录结构说明     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/03-design/roadmap/">
              <a href="http://shardingjdbc.io/document/legacy/1.x/cn/03-design/roadmap/">
                <span>未来线路规划     </i></span>
              </a>
            </li>
          
        </ul>
        
      </li>
      
      
    </ul>
    <hr>
     
  </div>
</nav>

        <section id="body">
        <div id="overlay"></div>

        <div class="padding highlightable">

            <div id="top-bar">
              
              <div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
                  <span id="sidebar-toggle-span">
                      <a href="#" id="sidebar-toggle" data-sidebar-toggle="">
                        <i class="fa fa-bars"></i>
                      </a>
                  </span>
                
                <span id="toc-menu"><a href=""><i class="fa fa-list-alt"></i></a></span>
                
                
                  
                  
                  
                    
                    
                <a href="http://shardingjdbc.io/document/legacy/1.x/cn/02-guide/" itemprop="url"><span itemprop="title">使用指南</span></a> <i class="fa fa-angle-right"></i>
                    
                  
                
                <span itemprop="title"> 分库分表</span>
              </div>
              
                  <div class="progress">
    <div class="wrapper">
<nav id="TableOfContents">
<ul>
<li>
<ul>
<li><a href="#数据库模式">数据库模式</a></li>
<li><a href="#逻辑表与实际表映射关系">逻辑表与实际表映射关系</a>
<ul>
<li><a href="#均匀分布">均匀分布</a></li>
<li><a href="#自定义分布">自定义分布</a></li>
<li><a href="#本教程采用的数据分布例子">本教程采用的数据分布例子</a></li>
</ul></li>
<li><a href="#逻辑表与实际表">逻辑表与实际表</a></li>
<li><a href="#规则配置">规则配置</a></li>
<li><a href="#数据源配置">数据源配置</a></li>
<li><a href="#策略配置">策略配置</a>
<ul>
<li><a href="#数据源策略与表策略">数据源策略与表策略</a></li>
<li><a href="#全局默认策略与特定表策略">全局默认策略与特定表策略</a></li>
<li><a href="#分片键">分片键</a></li>
<li><a href="#分片算法">分片算法</a></li>
<li><a href="#绑定表">绑定表</a></li>
</ul></li>
<li><a href="#分片算法详解">分片算法详解</a>
<ul>
<li><a href="#单分片键算法与多分片键算法">单分片键算法与多分片键算法</a></li>
<li><a href="#分片键算法类型">分片键算法类型</a></li>
<li><a href="#单分片键算法">单分片键算法</a></li>
<li><a href="#多分片键算法">多分片键算法</a></li>
</ul></li>
<li><a href="#构造shardingdatasource">构造ShardingDataSource</a></li>
<li><a href="#使用shardingdatasource">使用ShardingDataSource</a></li>
</ul></li>
</ul>
</nav>
    </div>
</div>

              

            </div>
            
              <div id="body-inner">
                
                <h1>分库分表</h1>
                



<p>阅读本指南前，请先阅读快速起步。本文档使用更复杂的场景进一步介绍Sharding-JDBC的分库分表能力。</p>

<h2 id="数据库模式">数据库模式</h2>

<p>本文档中提供了两个数据源db0和db1，每个数据源之中包含了两组表t_order_0和t_order_1，t_order_item_0和t_order_item_1 。这两组表的建表语句为：</p>

<pre><code class="language-sql">CREATE TABLE IF NOT EXISTS t_order_x (
  order_id INT NOT NULL,
  user_id  INT NOT NULL,
  PRIMARY KEY (order_id)
);
CREATE TABLE IF NOT EXISTS t_order_item_x (
  item_id  INT NOT NULL,
  order_id INT NOT NULL,
  user_id  INT NOT NULL,
  PRIMARY KEY (item_id)
);
</code></pre>

<h2 id="逻辑表与实际表映射关系">逻辑表与实际表映射关系</h2>

<h3 id="均匀分布">均匀分布</h3>

<p>数据表在每个数据源内呈现均匀分布的态势</p>

<pre><code>db0
  ├── t_order_0 
  └── t_order_1 
db1
  ├── t_order_0 
  └── t_order_1
</code></pre>

<p>表规则可以使用默认的配置</p>

<pre><code class="language-java"> TableRule orderTableRule = TableRule.builder(&quot;t_order&quot;).actualTables(Arrays.asList(&quot;t_order_0&quot;, &quot;t_order_1&quot;)).dataSourceRule(dataSourceRule).build();
</code></pre>

<h3 id="自定义分布">自定义分布</h3>

<p>数据表呈现有特定规则的分布</p>

<pre><code>db0
  ├── t_order_0 
  └── t_order_1 
db1
  ├── t_order_2
  ├── t_order_3
  └── t_order_4
</code></pre>

<p>表规则可以指定每张表在数据源中的分布情况</p>

<pre><code class="language-java"> TableRule orderTableRule = TableRule.builder(&quot;t_order&quot;).actualTables(Arrays.asList(&quot;db0.t_order_0&quot;, &quot;db0.t_order_1&quot;, &quot;db1.t_order_2&quot;, &quot;db1.t_order_3&quot;, &quot;db1.t_order_4&quot;)).dataSourceRule(dataSourceRule).build();
</code></pre>

<h3 id="本教程采用的数据分布例子">本教程采用的数据分布例子</h3>

<pre><code>db0
  ├── t_order_0               user_id为偶数   order_id为偶数
  ├── t_order_1               user_id为偶数   order_id为奇数
  ├── t_order_item_0          user_id为偶数   order_id为偶数
  └── t_order_item_1          user_id为偶数   order_id为奇数
db1
  ├── t_order_0               user_id为奇数   order_id为偶数
  ├── t_order_1               user_id为奇数   order_id为奇数
  ├── t_order_item_0          user_id为奇数   order_id为偶数
  └── t_order_item_1          user_id为奇数   order_id为奇数
</code></pre>

<h2 id="逻辑表与实际表">逻辑表与实际表</h2>

<p>配置分库分表的目的是将原有一张表的数据分散到不同库不同表中，且不改变原有SQL语句的情况下来使用这一张表。那么从一张表到多张的映射关系需要使用逻辑表与实际表这两种概念。下面通过一个例子来解释一下。假设在使用PreparedStatement访问数据库，SQL如下：</p>

<pre><code class="language-sql">select * from t_order where user_id = ? and order_id = ?;
</code></pre>

<p>当user_id=0且order=0时，Sharding-JDBC将会将SQL语句转换为如下形式：</p>

<pre><code class="language-sql">select * from db0.t_order_0 where user_id = ? and order_id = ?;
</code></pre>

<p>其中原始SQL中的t_order就是 <strong>逻辑表</strong>，而转换后的db0.t_order_0就是 <strong>实际表</strong></p>

<h2 id="规则配置">规则配置</h2>

<p>以上分库分表的形式Sharding-JDBC是通过规则配置来进行的描述的，下面讲通过几个小节来描述规则的详细配置：</p>

<pre><code class="language-java"> ShardingRule shardingRule = ShardingRule.builder()
        .dataSourceRule(dataSourceRule)
        .tableRules(Arrays.asList(orderTableRule, orderItemTableRule))
        .databaseShardingStrategy(new DatabaseShardingStrategy(&quot;user_id&quot;, new ModuloDatabaseShardingAlgorithm()))
        .tableShardingStrategy(new TableShardingStrategy(&quot;order_id&quot;, new ModuloTableShardingAlgorithm()))
        .build();
</code></pre>

<h2 id="数据源配置">数据源配置</h2>

<p>首先我们来构造DataSourceRule对象，它是来描述数据源的分布规则的。</p>

<pre><code class="language-java"> DataSourceRule dataSourceRule = new DataSourceRule(dataSourceMap);
</code></pre>

<p>这里构造器需要一个入参：数据源名称与真实数据源之间的映射关系，这个关系的构造方法如下</p>

<pre><code class="language-java">Map&lt;String, DataSource&gt; dataSourceMap = new HashMap&lt;&gt;(2);
dataSourceMap.put(&quot;ds_0&quot;, createDataSource(&quot;ds_0&quot;));
dataSourceMap.put(&quot;ds_1&quot;, createDataSource(&quot;ds_1&quot;));
</code></pre>

<p>真实的数据源可以使用任意一种数据库连接池，这里使用DBCP来举例</p>

<pre><code class="language-java">private static DataSource createDataSource(final String dataSourceName) {
    BasicDataSource result = new BasicDataSource();
    result.setDriverClassName(com.mysql.jdbc.Driver.class.getName());
    result.setUrl(String.format(&quot;jdbc:mysql://localhost:3306/%s&quot;, dataSourceName));
    result.setUsername(&quot;root&quot;);
    result.setPassword(&quot;&quot;);
    return result;
}
</code></pre>

<h2 id="策略配置">策略配置</h2>

<h3 id="数据源策略与表策略">数据源策略与表策略</h3>

<p><img src="../../img/StrategyClass.900.png" alt="策略类图" />
Sharding-JDBC认为对于分片策略存有两种维度
- 数据源分片策略DatabaseShardingStrategy：数据被分配的目标数据源
- 表分片策略TableShardingStrategy：数据被分配的目标表，该目标表存在与该数据的目标数据源内。故表分片策略是依赖与数据源分片策略的结果的
这里注意的是两种策略的API完全相同，以下针对策略API的讲解将适用于这两种策略</p>

<h3 id="全局默认策略与特定表策略">全局默认策略与特定表策略</h3>

<p>策略是作用在特定的表规则上的，数据源策略与表策略与特定表相关</p>

<pre><code class="language-java"> TableRule orderTableRule = TableRule.builder(&quot;t_order&quot;)
         .actualTables(Arrays.asList(&quot;t_order_0&quot;, &quot;t_order_1&quot;)
         .dataSourceRule(dataSourceRule)
         .databaseShardingStrategy(new DatabaseShardingStrategy(&quot;user_id&quot;, new ModuloDatabaseShardingAlgorithm()))
         .tableShardingStrategy(new TableShardingStrategy(&quot;order_id&quot;, new ModuloTableShardingAlgorithm())))
         .build();
</code></pre>

<p>如果分片规则中的所有表或大部分表的分片策略相同，可以使用默认策略来简化配置。以下两种配置是等价的:</p>

<pre><code class="language-java">  //使用了默认策略配置
  TableRule orderTableRule = TableRule.builder(&quot;t_order&quot;)
          .actualTables(Arrays.asList(&quot;t_order_0&quot;, &quot;t_order_1&quot;))
          .dataSourceRule(dataSourceRule)
          .build();
  TableRule orderItemTableRule = TableRule.builder(&quot;t_order_item&quot;)
            .actualTables(Arrays.asList(&quot;t_order_item_0&quot;, &quot;t_order_item_1&quot;))
            .dataSourceRule(dataSourceRule)
            .build();
  ShardingRule shardingRule = ShardingRule.builder()
            .dataSourceRule(dataSourceRule)
            .tableRules(Arrays.asList(orderTableRule, orderItemTableRule))
            .databaseShardingStrategy(new DatabaseShardingStrategy(&quot;user_id&quot;, new ModuloDatabaseShardingAlgorithm()))
            .tableShardingStrategy(new TableShardingStrategy(&quot;order_id&quot;, new ModuloTableShardingAlgorithm()))
            .build();
</code></pre>

<pre><code class="language-java">  //未使用默认策略配置
  TableRule orderTableRule = TableRule.builder(&quot;t_order&quot;)
          .actualTables(Arrays.asList(&quot;t_order_0&quot;, &quot;t_order_1&quot;))
          .dataSourceRule(dataSourceRule)
          .build();
  TableRule orderItemTableRule = TableRule.builder(&quot;t_order_item&quot;)
            .actualTables(Arrays.asList(&quot;t_order_item_0&quot;, &quot;t_order_item_1&quot;))
            .dataSourceRule(dataSourceRule)
            .databaseShardingStrategy(new DatabaseShardingStrategy(&quot;user_id&quot;, new ModuloDatabaseShardingAlgorithm()))
            .tableShardingStrategy(new TableShardingStrategy(&quot;order_id&quot;, new ModuloTableShardingAlgorithm()))
            .build();
  ShardingRule shardingRule = ShardingRule.builder()
            .dataSourceRule(dataSourceRule)
            .tableRules(Arrays.asList(orderTableRule, orderItemTableRule))
            .databaseShardingStrategy(new DatabaseShardingStrategy(&quot;user_id&quot;, new ModuloDatabaseShardingAlgorithm()))
            .tableShardingStrategy(new TableShardingStrategy(&quot;order_id&quot;, new ModuloTableShardingAlgorithm()))
            .build();
</code></pre>

<h3 id="分片键">分片键</h3>

<p>分片键是分片策略的第一个参数。分片键表示的是SQL语句中WHERE中的条件列。分片键可以配置多个</p>

<ul>
<li>单分片策略</li>
</ul>

<pre><code class="language-java">new TableShardingStrategy(&quot;order_id&quot;, new SingleKeyShardingAlgorithm()))
</code></pre>

<ul>
<li>多分片策略</li>
</ul>

<pre><code class="language-java">new TableShardingStrategy(Arrays.asList(&quot;order_id&quot;, &quot;order_type&quot;, &quot;order_date&quot;), new MultiKeyShardingAlgorithm()))
</code></pre>

<h3 id="分片算法">分片算法</h3>

<p>分片算法接口类图关系如下：</p>

<p><img src="../../img/AlgorithmClass.900.png" alt="算法" /></p>

<h3 id="绑定表">绑定表</h3>

<p>绑定表代表一组表，这组表的逻辑表与实际表之间的映射关系是相同的。比如t_order与t_order_item就是这样一组绑定表关系,它们的分库与分表策略是完全相同的,那么可以使用它们的表规则将它们配置成绑定表</p>

<pre><code class="language-java">new BindingTableRule(Arrays.asList(orderTableRule, orderItemTableRule))
</code></pre>

<p>那么在进行SQL路由时，如果SQL为</p>

<pre><code class="language-sql">SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=?
</code></pre>

<p>其中t_order在FROM的最左侧，Sharding-JDBC将会以它作为整个绑定表的主表。所有路由计算将会只使用主表的策略，那么t_order_item表的分片计算将会使用t_order的条件。故绑定表之间的分区键要完全相同。</p>

<h2 id="分片算法详解">分片算法详解</h2>

<h3 id="单分片键算法与多分片键算法">单分片键算法与多分片键算法</h3>

<p>这两种算法从名字上就可以知道前者是针对只有一个分片键，后者是针对有多个分片键的。单分片键算法是多分片键算法的一种简便形式，所以完全可以使用多分片算法去替代单分片键算法。下面两种形式是等价的</p>

<pre><code class="language-java">new TableShardingStrategy(&quot;order_id&quot;, new SingleKeyShardingAlgorithm()))
new TableShardingStrategy(Arrays.asList(&quot;order_id&quot;), new MultiKeyShardingAlgorithm()))
</code></pre>

<p>同时在算法内部，doSharding等方法的shardingValue入参根据使用算法类型不同而不同
单分片键算法，方法签名</p>

<pre><code class="language-java">public String doEqualSharding(final Collection&lt;String&gt; dataSourceNames, final ShardingValue&lt;Integer&gt; shardingValue) 
</code></pre>

<p>多分片键算法，方法签名</p>

<pre><code class="language-java">public Collection&lt;String&gt; doSharding(final Collection&lt;String&gt; availableTargetNames, final Collection&lt;ShardingValue&lt;?&gt;&gt; shardingValues)
</code></pre>

<h3 id="分片键算法类型">分片键算法类型</h3>

<p>根据数据源策略与表策略、单分片与多分片，这两种组合，一共产生了4种可供实现的分片算法的接口</p>

<ul>
<li>单分片键数据源分片算法SingleKeyDatabaseShardingAlgorithm</li>
<li>单分片表分片算法SingleKeyTableShardingAlgorithm</li>
<li>多分片键数据源分片算法MultipleKeyDatabaseShardingAlgorithm</li>
<li>多分片表分片算法MultipleKeyTableShardingAlgorithm</li>
</ul>

<h3 id="单分片键算法">单分片键算法</h3>

<p>单分片键算法需要实现三个方法，下面以”单分片键数据源分片算法“举例</p>

<pre><code class="language-java">@Override
public String doEqualSharding(final Collection&lt;String&gt; availableTargetNames, final ShardingValue&lt;Integer&gt; shardingValue)

@Override
public Collection&lt;String&gt; doInSharding(final Collection&lt;String&gt; availableTargetNames, final ShardingValue&lt;Integer&gt; shardingValue)

@Override
public Collection&lt;String&gt; doBetweenSharding(final Collection&lt;String&gt; availableTargetNames, final ShardingValue&lt;Integer&gt; shardingValue)
</code></pre>

<p>这三种算法作用如下
- doEqualSharding在WHERE使用=作为条件分片键。算法中使用shardingValue.getValue()获取等=后的值
- doInSharding在WHERE使用IN作为条件分片键。算法中使用shardingValue.getValues()获取IN后的值
- doBetweenSharding在WHERE使用BETWEEN作为条件分片键。算法中使用shardingValue.getValueRange()获取BETWEEN后的值</p>

<p>下面是一个余2的算法的例子，当分片键的值除以2余数就是实际表的结尾。注意注释中提供了一些算法生成SQL的结果，参数tableNames集合中有两个参数t_order_0和t_order_1</p>

<pre><code class="language-java"> public final class ModuloTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm&lt;Integer&gt; {
    
    /**
    *  select * from t_order from t_order where order_id = 11 
    *          └── SELECT *  FROM t_order_1 WHERE order_id = 11
    *  select * from t_order from t_order where order_id = 44
    *          └── SELECT *  FROM t_order_0 WHERE order_id = 44
    */
    public String doEqualSharding(final Collection&lt;String&gt; tableNames, final ShardingValue&lt;Integer&gt; shardingValue) {
        for (String each : tableNames) {
            if (each.endsWith(shardingValue.getValue() % 2 + &quot;&quot;)) {
                return each;
            }
        }
        throw new IllegalArgumentException();
    }
    
    /**
    *  select * from t_order from t_order where order_id in (11,44)  
    *          ├── SELECT *  FROM t_order_0 WHERE order_id IN (11,44) 
    *          └── SELECT *  FROM t_order_1 WHERE order_id IN (11,44) 
    *  select * from t_order from t_order where order_id in (11,13,15)  
    *          └── SELECT *  FROM t_order_1 WHERE order_id IN (11,13,15)  
    *  select * from t_order from t_order where order_id in (22,24,26)  
    *          └──SELECT *  FROM t_order_0 WHERE order_id IN (22,24,26) 
    */
    public Collection&lt;String&gt; doInSharding(final Collection&lt;String&gt; tableNames, final ShardingValue&lt;Integer&gt; shardingValue) {
        Collection&lt;String&gt; result = new LinkedHashSet&lt;&gt;(tableNames.size());
        for (Integer value : shardingValue.getValues()) {
            for (String tableName : tableNames) {
                if (tableName.endsWith(value % 2 + &quot;&quot;)) {
                    result.add(tableName);
                }
            }
        }
        return result;
    }
    
    /**
    *  select * from t_order from t_order where order_id between 10 and 20 
    *          ├── SELECT *  FROM t_order_0 WHERE order_id BETWEEN 10 AND 20 
    *          └── SELECT *  FROM t_order_1 WHERE order_id BETWEEN 10 AND 20 
    */
    public Collection&lt;String&gt; doBetweenSharding(final Collection&lt;String&gt; tableNames, final ShardingValue&lt;Integer&gt; shardingValue) {
        Collection&lt;String&gt; result = new LinkedHashSet&lt;&gt;(tableNames.size());
        Range&lt;Integer&gt; range = (Range&lt;Integer&gt;) shardingValue.getValueRange();
        for (Integer i = range.lowerEndpoint(); i &lt;= range.upperEndpoint(); i++) {
            for (String each : tableNames) {
                if (each.endsWith(i % 2 + &quot;&quot;)) {
                    result.add(each);
                }
            }
        }
        return result;
    }
}
</code></pre>

<h3 id="多分片键算法">多分片键算法</h3>

<p>多分片键试用于使用场景比较复杂，为了能提供更高的灵活性，故只提供实现一个方法。</p>

<pre><code class="language-java">@Override
public Collection&lt;String&gt; doSharding(final Collection&lt;String&gt; availableTargetNames, final Collection&lt;ShardingValue&lt;?&gt;&gt; shardingValues)
</code></pre>

<p>算法实现的时候根据shardingValue.getType()来获取条件是=，IN或者BETWEEN。然后根据业务进行灵活的实现。</p>

<p>如果表的数据分布如下</p>

<pre><code>db0
  ├── t_order_00               user_id以a偶数   order_id为偶数
  ├── t_order_01               user_id以a偶数   order_id为奇数
  ├── t_order_10               user_id以b奇数   order_id为偶数
  └── t_order_11               user_id以b奇数   order_id为奇数

</code></pre>

<p>算法实现如下:</p>

<pre><code class="language-java">public final class MultipleKeysModuloTableShardingAlgorithm implements MultipleKeysTableShardingAlgorithm {
    
    @Override
    public Collection&lt;String&gt; doSharding(final Collection&lt;String&gt; availableTargetNames, final Collection&lt;ShardingValue&lt;?&gt;&gt; shardingValues) {
        Set&lt;Integer&gt; orderIdValueSet = getShardingValue(shardingValues, &quot;order_id&quot;);
        Set&lt;Integer&gt; userIdValueSet = getShardingValue(shardingValues, &quot;user_id&quot;);
    
        List&lt;String&gt; result = new ArrayList&lt;&gt;();
        /*
        userIdValueSet[10,11] + orderIdValueSet[101,102] =&gt; valueResult[[10,101],[10,102],[11,101],[11,102]]
         */
        Set&lt;List&lt;Integer&gt;&gt; valueResult = Sets.cartesianProduct(userIdValueSet, orderIdValueSet);
        for (List&lt;Integer&gt; value : valueResult) {
            String suffix = Joiner.on(&quot;&quot;).join(value.get(0) % 2, value.get(1) % 2);
            for (String tableName : availableTargetNames) {
                if (tableName.endsWith(suffix)) {
                    result.add(tableName);
                }
            }
        
        }
        return result;
    }
    
    private Set&lt;Integer&gt; getShardingValue(final Collection&lt;ShardingValue&lt;?&gt;&gt; shardingValues, final String shardingKey) {
        Set&lt;Integer&gt; valueSet = new HashSet&lt;&gt;();
        ShardingValue&lt;Integer&gt; shardingValue = null;
        for (ShardingValue&lt;?&gt; each : shardingValues) {
            if (each.getColumnName().equals(shardingKey)) {
                shardingValue = (ShardingValue&lt;Integer&gt;) each;
                break;
            }
        }
        if (null == shardingValue) {
            return valueSet;
        }
        switch (shardingValue.getType()) {
            case SINGLE:
                valueSet.add(shardingValue.getValue());
                break;
            case LIST:
                valueSet.addAll(shardingValue.getValues());
                break;
            case RANGE:
                for (Integer i = shardingValue.getValueRange().lowerEndpoint(); i &lt;= shardingValue.getValueRange().upperEndpoint(); i++) {
                    valueSet.add(i);
                }
                break;
            default:
                throw new UnsupportedOperationException();
        }
        return valueSet;
    }
}
</code></pre>

<h2 id="构造shardingdatasource">构造ShardingDataSource</h2>

<p>完成规则配置后，我们可以通过ShardingDataSourceFactory工厂得到ShardingDataSource</p>

<pre><code class="language-java">DataSource dataSource = ShardingDataSourceFactory.createDataSource(shardingRule);
</code></pre>

<h2 id="使用shardingdatasource">使用ShardingDataSource</h2>

<p>通过一个例子来看看如何使用该数据源</p>

<pre><code class="language-java">String sql = &quot;SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=?&quot;;
        try (
                Connection conn = dataSource.getConnection();
                PreparedStatement preparedStatement = conn.prepareStatement(sql);
                ) {
            preparedStatement.setInt(1, 10);
            preparedStatement.setInt(2, 1001);
            ResultSet rs = preparedStatement.executeQuery();
            while (rs.next()) {
                System.out.println(rs.getInt(1));
                System.out.println(rs.getInt(2));
                System.out.println(rs.getInt(3));
            }
            rs.close();
        }
</code></pre>

<p>该数据源与普通数据源完全相同，你可以通过上例的API形式来使用，也可以将其配置在Spring，Hibernate等框架中使用。</p>

<blockquote>
<p>如果希望不依赖于表中的列传入分片键值，参考：<a href="http://shardingjdbc.io/document/legacy/1.x/cn/02-guide/hint-sharding-value">强制路由</a></p>
</blockquote>


      
      
      </div>
    </div>

    

    <div id="navigation">
        
        <a class="nav nav-prev" href="http://shardingjdbc.io/document/legacy/1.x/cn/02-guide/concepts/"> <i class="fa fa-chevron-left"></i></a>
        <a class="nav nav-next" href="http://shardingjdbc.io/document/legacy/1.x/cn/02-guide/master-slave/" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
    </div>

    </section>
    <div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
      <div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
    </div>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/clipboard.min.js"></script>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/perfect-scrollbar.min.js"></script>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/perfect-scrollbar.jquery.min.js"></script>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/jquery.sticky-kit.min.js"></script>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/featherlight.min.js"></script>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/html5shiv-printshiv.min.js"></script>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/highlight.pack.js"></script>
    <script>hljs.initHighlightingOnLoad();</script>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/learn.js"></script>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/hugo-learn.js"></script>
    <script src="http://cdn.bootcss.com/highlight.js/9.8.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>

  </body>
</html>

